package automatagen;

import java.util.ArrayList;

public class Tripla {
	
	private TriplaType type;
	private String first;
	private String oper;
	private String second;
	private ArrayList<Tripla> triplas = new ArrayList<Tripla>();
	
	public AccessMethod getAccessMethod(AutomataGen autGen){
		String[] pieces = first.split("[.]");
		AccessMethod accessMethod;
		switch (pieces.length) {
		case 1:
			accessMethod = new AccessMethod(this.first,"*" + pieces[0].replaceAll("[.]","_"),"");
			break;
		case 2:
			String fieldName = (String) autGen.getVarMaps().get(pieces[0]).getFields().get(pieces[1]).getValues().keySet().toArray()[0];
			String regName = autGen.getVarMaps().get(pieces[0]).getFields().get(pieces[1]).getValues().get(fieldName);
			RegisterMap reg2 = autGen.getRegs().get(regName); 
			if (fieldName != regName){
				FormatField field = reg2.getFormat().getFields().get(fieldName);
				String methodName = this.first;
				String methodSignature = "GET_" + first.toUpperCase().replaceAll("[.]", "_") + "(*" + reg2.getName() + ")";
				String methodCode = "#define GET_" + first.toUpperCase().replaceAll("[.]", "_") + "(value)\t\t\t" +  
									"((value & " + Integer.parseInt(generateFieldMaskFilter(field.getEnd(),field.getSize()),2) + ") >> " + field.getStart() + ")";
				accessMethod = new AccessMethod(methodName, methodSignature, methodCode);
			}else{
				accessMethod = new AccessMethod(this.first,"*" + reg2.getName(),"");
			}
			break;
		case 3:
			RegisterMap reg3 = autGen.getRegs().get(autGen.getVarMaps().get(pieces[0]).getFields().get(pieces[1]).getValues().get(pieces[2]));
			FormatField field = reg3.getFormat().getFields().get(pieces[2]);
			String methodName = this.first;
			String methodSignature = "GET_" + first.toUpperCase().replaceAll("[.]", "_") + "(*" + reg3.getName() + ")";
			String methodCode = "#define GET_" + first.toUpperCase().replaceAll("[.]", "_") + "(value)\t\t\t" +  
								"((value & " + Integer.parseInt(generateFieldMaskFilter(field.getEnd(),field.getSize()),2) + ") >> " + field.getStart() + ")";
			accessMethod = new AccessMethod(methodName, methodSignature, methodCode);
			break;
		default:
			accessMethod = null;
		}
		autGen.addAccessMethod(accessMethod.getName(), accessMethod);
		return accessMethod;
	}
	
	private String generateFieldMaskFilter(int end, int size){
		StringBuffer sb = new StringBuffer();
		for (int i = end;i>=0;i--){
			if (i > end - size){
				sb.append("1");
			}else{
				sb.append("0");
			}
		}
		return sb.toString();
	}
	
	public TriplaType getType() {
		return type;
	}

	public void setType(TriplaType type) {
		this.type = type;
	}

	public String getFirst() {
		return first;
	}

	public void setFirst(String first) {
		this.first = first;
	}

	public String getOper() {
		return oper;
	}

	public void setOper(String oper) {
		this.oper = oper;
	}

	public String getSecond() {
		return second;
	}

	public void setSecond(String second) {
		this.second = second;
	}

	public ArrayList<Tripla> getTriplas() {
		return triplas;
	}
	
	public void setTriplas(ArrayList<Tripla> triplas) {
		if (triplas == null){
			this.triplas = new ArrayList<Tripla>();
		}else{
			this.triplas = triplas;
		}
	}

	public Tripla(String first, String oper, String second) {
		type = TriplaType.CONDITIONAL;
		this.first = first;
		this.oper = oper;
		this.second = second;
	}
	
	public Tripla(String first, String second) {
		type = TriplaType.ASSIGNMENT;
		this.first = first;
		this.oper = "==";
		this.second = second;
	}

	public boolean equals(Tripla o) {
		if (o.getFirst().equals(this.getFirst()) && o.oper.equals(this.oper) && o.getSecond().equals(this.getSecond())){
			return true;
		}else{
			return false;
		}
	}
	
	
}
